#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "aceMesh_runtime_c.h"
#include "gauss_aceMesh.h"
#include "slave.h"
__thread_local_fix int i,j,k,s_starti,s_endi,s_startj,s_endj,s_startk,s_endk,s_BS,tsize,stride,bsize;
__thread_local volatile unsigned long get_reply,put_reply;
#if ((BS+2)*(BS+2)*8/1024<64)
__thread_local double s_A[BS+2][BS+2];
#else
#define TASK_FLOW
__thread_local double s_A[TASK_BSIZE_1+2][TASK_BSIZE_1+2];
__thread_local int ii,jj,kk;
#endif
extern double A[N][N];

#ifdef INST_PERF
extern unsigned long inst_count[64];
__thread_local unsigned long inst_start;
__thread_local unsigned long inst_end;
__thread_local unsigned long local_inst;
#endif

void stencil_core(targs* args)
{
#ifdef INST_PERF
    penv_slave0_inst_count(&inst_start);
#endif
    s_starti=args->starti;
    s_endi=args->endi;
    s_startj=args->startj;
    s_endj=args->endj;
    s_BS=args->_BS;
    
#ifdef MMEM
    for(i = s_starti; i < s_endi; i++)
    for(j = s_startj; j < s_endj; j++)
        A[i][j] = 0.2* (A[i][j] + A[i-1][j]+A[i+1][j] + A[i][j-1] + A[i][j+1]);
#else
#ifdef TASK_FLOW
    bsize=(TASK_BSIZE_1+2)*8;
    stride=(N-(TASK_BSIZE_1+2))*8;
    tsize=(TASK_BSIZE_1+2)*bsize;
    get_reply=0;
    for(ii=s_starti;ii<s_endi;ii+=TASK_BSIZE_1){
      for(jj=s_startj;jj<s_endj;jj+=TASK_BSIZE_1){
        get_reply=0;
        athread_get(PE_MODE,&A[ii-1][jj-1]
                    , &s_A[0][0]
                    , tsize, (void*)&get_reply
                    , 0,stride,bsize);
        while(get_reply!=1);
        for(i =1; i < TASK_BSIZE_1+1; i++)
        for(j =1; j < TASK_BSIZE_1+1; j++)
           s_A[i][j] = 0.2* (s_A[i][j] + s_A[i-1][j]+s_A[i+1][j] + s_A[i][j-1] + s_A[i][j+1]);
        put_reply=0;
        athread_put(PE_MODE,&s_A[0][0]
                    ,&A[ii-1][jj-1]
                    ,tsize,(void*)&put_reply
                    ,stride,bsize);
        while(put_reply!=1);
      }

   }
#else
    bsize=(BS+2)*8;
    stride=(N-(BS+2))*8;
    tsize=(BS+2)*bsize;
    get_reply=0;
    athread_get(PE_MODE,&A[s_starti-1][s_startj-1]
               , &s_A[0][0]
               , tsize, (void*)&get_reply
               , 0,stride,bsize);
    while(get_reply!=1);
    for(i =1; i < s_BS+1; i++)
    for(j =1; j < s_BS+1; j++)
        s_A[i][j] = 0.2* (s_A[i][j] + s_A[i-1][j]+s_A[i+1][j] + s_A[i][j-1] + s_A[i][j+1]);
    put_reply=0;
    athread_put(PE_MODE,&s_A[0][0]
               ,&A[s_starti-1][s_startj-1]
               ,tsize,(void*)&put_reply
               ,stride,bsize);
    while(put_reply!=1);
#endif
#ifdef INST_PERF
    penv_slave0_inst_count(&inst_end);
    inst_count[_MYID]+=(inst_end-inst_start);
#endif
#endif
}
